home *** CD-ROM | disk | FTP | other *** search
- /*
- * This files contains routines for getting the "next" token.
- */
- #include "::preproc:preproc.h"
- #include "::preproc:ptoken.h"
- #include "::preproc:pproto.h"
-
- /*
- * next_tok - get the next raw token. No macros are expanded here (although
- * the tokens themselves may be the result of a macro expansion initiated
- * at a "higher" level). Only #line directives are processed here.
- */
- struct token *next_tok()
- {
- struct token *t, *t1;
- struct tok_lst *tlst;
- struct char_src *cs;
- struct str_buf *sbuf;
- char *s;
- char *fname;
- int n;
-
- if (src_stack->flag == DummySrc)
- return NULL; /* source stack is empty - end of input */
-
- /*
- * See if a directive pushed back any tokens.
- */
- if (src_stack->ntoks > 0)
- return src_stack->toks[--src_stack->ntoks];
-
- switch (src_stack->flag) {
- case CharSrc:
- /*
- * Tokens from a raw character "stream".
- */
- t = tokenize();
- if (t != NULL && src_stack->u.cs->f != NULL)
- t->flag |= LineChk;
- if (t != NULL && t->tok_id == PpLine) {
- /*
- * #line directives must be processed here so they are not
- * put in macros.
- */
- cs = src_stack->u.cs;
- t1 = NULL;
-
- /*
- * Get the line number from the directive.
- */
- advance_tok(&t1);
- if (t1->tok_id != PpNumber)
- errt1(t1, "#line requires an integer argument");
- n = 0;
- for (s = t1->image; *s != '\0'; ++s) {
- if (*s >= '0' && *s <= '9')
- n = 10 * n + (*s - '0');
- else
- errt1(t1, "#line requires an integer argument");
- }
-
- /*
- * Get the file name, if there is one, from the directive.
- */
- advance_tok(&t1);
- fname = NULL;
- if (t1->tok_id == StrLit) {
- sbuf = get_sbuf();
- for (s = t1->image; *s != '\0'; ++s) {
- if (s[0] == '\\' && (s[1] == '\\' || s[1] == '"'))
- ++s;
- AppChar(*sbuf, *s);
- }
- fname = str_install(sbuf);
- rel_sbuf(sbuf);
- advance_tok(&t1);
- }
- if (t1->tok_id != PpDirEnd)
- errt1(t1, "syntax error in #line");
-
- /*
- * Note the effect of the line directive in the character
- * source. Line number changes are handled as a relative
- * adjustments to the line numbers of following lines.
- */
- if (fname != NULL)
- cs->fname = fname;
- cs->line_adj = n - cs->line_buf[next_char - first_char + 1];
- if (*next_char == '\n')
- ++cs->line_adj; /* the next lines contains no characters */
-
- t = next_tok(); /* the caller does not see #line directives */
- }
- break;
-
- case MacExpand:
- /*
- * Tokens from macro expansion.
- */
- t = mac_tok();
- break;
-
- case TokLst:
- /*
- * Tokens from a macro argument.
- */
- tlst = src_stack->u.tlst;
- if (tlst == NULL)
- t = NULL;
- else {
- t = copy_t(tlst->t);
- src_stack->u.tlst = tlst->next;
- }
- break;
-
- case PasteLsts:
- /*
- * Tokens from token Pasting.
- */
- return paste();
- }
-
- if (t == NULL) {
- /*
- * We have exhausted this entry on the source stack without finding
- * a token to return.
- */
- pop_src();
- return next_tok();
- }
- else
- return t;
- }
-
- /*
- * Get the next raw non-white space token, freeing token that the argument
- * used to point to.
- */
- novalue nxt_non_wh(tp)
- struct token **tp;
- {
- register struct token *t;
-
- t = next_tok();
- while (t != NULL && t->tok_id == WhiteSpace) {
- free_t(t);
- t = next_tok();
- }
- free_t(*tp);
- *tp = t;
- }
-
- /*
- * advance_tok - skip past white space after expanding macros and
- * executing preprocessor directives. This routine may only be
- * called from within a preprocessor directive because it assumes
- * it will not see EOF (the input routines insure that a terminating
- * new-line, and thus, for a directive, the PpDirEnd token, will be
- * seen immediately before EOF).
- */
- novalue advance_tok(tp)
- struct token **tp;
- {
- struct token *t;
-
- t = interp_dir();
- while (t->tok_id == WhiteSpace) {
- free_t(t);
- t = interp_dir();
- }
- free_t(*tp);
- *tp = t;
- }
-
- /*
- * merge_whsp - merge a sequence of white space tokens into one token,
- * returning it along with the next token. Whether these are raw or
- * processed tokens depends on the token source function, t_src.
- */
- novalue merge_whsp(whsp, next_t, t_src)
- struct token **whsp;
- struct token **next_t;
- struct token *(*t_src)Params((noargs));
- {
- struct token *t1;
- struct str_buf *sbuf;
- int line = -1;
- char *fname = "";
- char *s;
-
- free_t(*whsp);
- t1 = (*t_src)();
- if (t1 == NULL || t1->tok_id != WhiteSpace)
- *whsp = NULL; /* no white space here */
- else {
- *whsp = t1;
- t1 = (*t_src)();
- if (t1 != NULL && t1->tok_id == WhiteSpace) {
- if (whsp_image == NoSpelling) {
- /*
- * We don't care what the white space looks like, so
- * discard the rest of it.
- */
- while (t1 != NULL && t1->tok_id == WhiteSpace) {
- free_t(t1);
- t1 = (*t_src)();
- }
- }
- else {
- /*
- * Must actually merge white space. Put it all white space
- * in a string buffer and use that as the image of the merged
- * token. The line number and file name of the new token
- * is that of the last token whose line number and file
- * name is important for generating #line directives in
- * the output.
- */
- sbuf = get_sbuf();
- if ((*whsp)->flag & LineChk) {
- line = (*whsp)->line;
- fname = (*whsp)->fname;
- }
- for (s = (*whsp)->image; *s != '\0'; ++s) {
- AppChar(*sbuf, *s);
- if (*s == '\n' && line != -1)
- ++line;
- }
- while (t1 != NULL && t1->tok_id == WhiteSpace) {
- if (t1->flag & LineChk) {
- line = t1->line;
- fname = t1->fname;
- }
- for (s = t1->image; *s != '\0'; ++s) {
- AppChar(*sbuf, *s);
- if (*s == '\n' && line != -1)
- ++line;
- }
- free_t(t1);
- t1 = (*t_src)();
- }
- (*whsp)->image = str_install(sbuf);
- rel_sbuf(sbuf);
- if (t1 != NULL && !(t1->flag & LineChk) && line != -1) {
- t1->flag |= LineChk;
- t1->line = line;
- t1->fname = fname;
- }
- }
- }
- }
- *next_t = t1;
- }
-